Skip to content

feat(sdk): add support to path addressed requests in sdk - #546

Open
MCarlomagno wants to merge 9 commits into
mainfrom
feat/use-new-storage-endpoints-in-sdk
Open

feat(sdk): add support to path addressed requests in sdk#546
MCarlomagno wants to merge 9 commits into
mainfrom
feat/use-new-storage-endpoints-in-sdk

Conversation

@MCarlomagno

Copy link
Copy Markdown
Member

Closes #527.

Summary

Updates the Rust and JavaScript SDKs to use the path-addressed storage routes introduced in #536 and #543:

https://_pubky.{owner}/storage/{owner}/{path}
Path-addressed transport Legacy transport
Example /storage/{owner}/pub/file.txt /pub/file.txt
Storage owner {owner} path segment pubky-host
pubky-host Omitted Sent
SDK support Generated by new SDKs Accepted when parsing transport URLs

resolve_pubky, resolvePubky, and PubkyResource::to_transport_url now produce the path-addressed form. PubkyResource::from_transport_url accepts both forms, taking the owner from the path for canonical URLs even when the request uses an explicit homeserver authority.

Acceptance criteria

  • Public and session storage operations use /storage/{owner}/....
  • resolve_pubky, resolvePubky, and to_transport_url return path-addressed URLs.
  • Canonical and legacy transport URLs remain parseable.
  • The path owner is authoritative when an explicit homeserver authority is used.
  • Native, WASM, and JavaScript storage requests omit pubky-host.
  • Cookie signup and session requests retain pubky-host.
  • Logical Pubky addresses and session-relative APIs remain unchanged.
  • Old-SDK/new-homeserver interoperability uses the legacy pubky-host wire shape.
  • Cookie-only compatibility APIs identify their grant-backed replacements.
  • Shared grant-compatible APIs remain non-deprecated.
  • SDK documentation and transport URL examples use the path-addressed form.

@MCarlomagno
MCarlomagno requested review from 86667 and andrei-21 August 10, 2026 20:29
@@ -220,39 +221,35 @@ impl PubkyResource {
/// - Returns [`Error::Request`] if the constructed transport URL is invalid.
pub fn to_transport_url(&self) -> Result<Url, Error> {
let rel = self.path.as_str().trim_start_matches('/');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line appears in multiple methods. You didn't really touched this code, but would it make sense to encapsulate or make it somehow reusable?.

/// Render as `https://_pubky.<owner>/<abs-path>` for transport.
/// Render as `https://_pubky.<owner>/storage/<owner>/<abs-path>` for transport.
///
/// This converts the addressed resource into the actual homeserver URL used

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment and the implementation confuse me. By the actual homeserver URL I would expect homeserver's host or something. Maybe I miss something in terminology here?..

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes right, I didn't notice the confusing wording, I will replace by something like

"/// Converts the resource into its canonical transport URL"

let rel = self.path.as_str().trim_start_matches('/');
let https = format!("https://_pubky.{}/{}", self.owner.z32(), rel);
let owner = self.owner.z32();
let https = format!("https://_pubky.{owner}/storage/{owner}/{rel}");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI claims that session.storage().list("/") will not work anymore, because the server allows to list /pub or /priv. Is it intentional?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes intended, since we implemented /priv / /pub paths.
Maybe it wasn't explicit in the sdk before, but the rule is established in the homeserver here and here is the reason

@MCarlomagno
MCarlomagno requested a review from andrei-21 August 13, 2026 21:41
.ok_or_else(|| RequestError::Validation {
message: "path-addressed storage URL is missing a resource path".to_string(),
})?;
let owner = PublicKey::try_from_z32(owner).map_err(|_error| RequestError::Validation {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also should reject URLs like https://_pubky.<A>/storage/<B>/... where A != B.

@MCarlomagno
MCarlomagno requested a review from andrei-21 August 14, 2026 12:43
let https = format!("https://_pubky.{}/{}", self.owner.z32(), rel);
let owner = self.owner.z32();
let path = self.path.as_root_relative_str();
let https = format!("https://_pubky.{owner}/storage/{owner}/{path}");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From AI:
The SDK now has two storage URL formats:

  • Old homeservers expect:
    https://_pubky.<user>/pub/file.txt
  • New homeservers support:
    https://_pubky.<user>/storage/<user>/pub/file.txt

The high-level SDK methods, such as storage().get(...), first ask the homeserver which format it supports. If it is old, the SDK rewrites the URL to the legacy format. So those methods work correctly.

The problem is that public helpers like to_transport_url() always return the new format. If someone passes that URL to a normal HTTP client—or the public synchronous PubkyHttpClient::request()—the compatibility check never happens. An old homeserver receives /storage/..., does not recognize it, and the request fails.

So, in short:

The SDK knows how to support old servers, but that support only exists in the high-level request path. Publicly generated URLs bypass it.

This only affects callers using raw URLs or the low-level request API. Users of storage().get(), put(), etc. are already covered. The likely fixes are either to keep public URLs in the old compatible format or make the public request API perform the same feature negotiation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sdk] Use path-addressed URLs for storage requests

2 participants